%{
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "parser.h"

/* allocate and construct a string from the current token */
static void scan_identifier(char * str, int strlen)
{
  yylval.str_val = (char *) malloc(strlen + 1);
  strncpy(yylval.str_val, str, strlen);
  yylval.str_val[strlen] = '\0';  
}

/* allocate and construct a string literal */
static void scan_string(char * str, int strlen)
{
  yylval.str_val = (char *) malloc(strlen-2 + 1);
  strncpy(yylval.str_val, str+1, strlen-2);
  yylval.str_val[strlen-2] = '\0';
}

static void scan_int(char * str, int strlen)
{
  char text[100];
  assert(strlen < 100);
  /* convert to a null-terminated string */
  strncpy(text, str, strlen);
  text[strlen] = '\0';
  /* convert to an int */
  yylval.int_val = atoi(text);
}

static void scan_double(char * str, int strlen)
{
  char text[100];
  assert(strlen < 100);
  /* convert to a null-terminated string */
  strncpy(text, str, strlen);
  text[strlen] = '\0';
  /* convert to a double */
  yylval.dbl_val = atof(text);
}

%}

%option yylineno noyywrap nounput noinput never-interactive
%x COMMENT
%x COMMENT_SL

IDENT        [[:alpha:]][[:alnum:]]*
STRING       \"[[:print:]]*\"
REAL         [[:digit:]]*(\.[[:digit:]]+)?([eE][\+\-]?[[:digit:]]+)?
NATURAL      [[:digit:]]+

%%

"/*"          BEGIN(COMMENT);

<COMMENT>{
    "*/"      BEGIN(INITIAL);
    [^*\n]+   ;
    "*"[^/]   ;
    \n        ;
}

"//"          BEGIN(COMMENT_SL);
<COMMENT_SL>{
    [^\n]+    ;
    "\n"      BEGIN(INITIAL);
}
  

[[:space:]]   ;

","       { return T_COMMA; }
";"       { return T_SEMICOLON; }
":"       { return T_COLON; }
"("       { return T_OPEN_PAREN; }
")"       { return T_CLOSE_PAREN; }
"["       { return T_OPEN_BOX; }
"]"       { return T_CLOSE_BOX; }
"{"       { return T_OPEN_BRACE; }
"}"       { return T_CLOSE_BRACE; }
"="       { return T_EQUAL; }
"!="      { return T_NOT_EQUAL; }
"&"       { return T_AND; }
"|"       { return T_OR;}
"~"       { return T_TILDE; }
"#"       { return T_SHARP; }

null       { return T_NULL; }
type       { return T_TYPE; }
guaranteed { return T_GUARANTEED; }
random     { return T_RANDOM; }
nonrandom  { return T_NON_RANDOM; }
generating { return T_ORIGIN; /*deprecated */}
origin     { return T_ORIGIN; }
obs        { return T_OBS; }
query      { return T_QUERY; }
if         { return T_IF; }
then       { return T_THEN; }
elseif     { return T_ELSEIF; }
else       { return T_ELSE; }


{NATURAL}      { scan_int(yytext, yyleng); return T_NATURAL_NUM; }

{REAL}         { scan_double(yytext, yyleng); return T_REAL_NUM;}

{STRING}       { scan_string(yytext, yyleng); return T_STRING; }

{IDENT}        { scan_identifier(yytext, yyleng); return T_IDENTIFIER; }

.              { scan_identifier(yytext, yyleng); return T_UNKNOWN; }

